import 'dart:convert';
import 'dart:math';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:kxy_flutter_app/auth.dart';
import 'package:kxy_flutter_app/model/http_result.dart';
import 'extensions.dart';
import 'package:dio/dio.dart';
import 'dart:io';

class Http {
  Dio _dio = new Dio();
  static Http _http;

  static Http get instance {
    if (_http == null) {
      _http = new Http();
    }
    return _http;
  }

  Http() {
    _dio.options.baseUrl = 'http://api.yuzhekeji.club';
    // _dio.options.baseUrl = 'http://192.168.10.149:12346';
    // _dio.options.baseUrl = 'http://47.93.216.200:12348';

    // const bool inProduction = const bool.fromEnvironment("dart.vm.product");
    // if (inProduction) {
    //    _dio.options.baseUrl = 'http://47.93.216.200:12348';
    // } else {
    // _dio.options.baseUrl = 'http://192.168.10.81:12346';
    // }

    _dio.options.connectTimeout = 5000;
    _dio.options.receiveTimeout = 3000;
    _dio.options.contentType = 'application/x-www-form-urlencoded;charset=UTF-8';
    _dio.options.responseDecoder = null;

    _dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (RequestOptions options) async {
          return options;
        },
        onResponse: (Response response) async {
          return response;
        },
        onError: (DioError error) async {
          return error;
        },
      ),
    );
  }

  Future<bool> download(String url, String path) async {
    var res = await _dio.download(url, path);
    return res.statusCode == 200;
  }

  Future<String> uploadFile(File file) async {
    var tokenRes = await post('/sys/oss/imguptoken');
    var token = tokenRes.data['token'].toString();
    var domain = tokenRes.data['domain'].toString();

    var random = new Random();
    var randomNumber = random.nextInt(10000);
    var upFile = MultipartFile.fromFileSync(file.path);
    if (upFile.length > 1024 * 1024 * 4) {
      Fluttertoast.showToast(msg: '图片大小不能超过4M');
      return '';
    }

    FormData formData = FormData.fromMap({
      'file': upFile,
      'key': DateTime.now().millisecondsSinceEpoch.toString() + randomNumber.toString(),
      'token': token,
    });

    var dio = new Dio();
    var uploadRes = await dio.post('http://up-z1.qiniup.com', data: formData);
    return domain + '/' + uploadRes.data['key'];
  }

  Future<Response> postData(String url, {Map<String, dynamic> params, bool withEntry = true}) async {
    if (params == null) {
      params = new Map<String, dynamic>();
    }

    if (withEntry) {
      _wrapParams(params);
    }

    _dio.options.headers['tenantId'] = Auth.instance.tenantId;
    var response = await _dio.post(url, data: params);
    return response;
  }

  Future<HttpResult> post(String url, {Map<String, dynamic> params, bool withEntry = true}) async {
    if (params == null) {
      params = new Map<String, dynamic>();
    }

    if (withEntry) {
      _wrapParams(params);
    }

    _dio.options.headers['tenantId'] = Auth.instance.tenantId;

    try {
      var response = await _dio.post(url, data: params);
      dynamic dynamicData;
      if (response.data is String) {
        dynamicData = jsonDecode(response.data);
      } else {
        dynamicData = response.data;
      }
      return HttpResult.fromJson(dynamicData as Map<String, dynamic>);
    } catch (ex) {
      return new HttpResult(
        code: 500,
        msg: '服务器异常了',
        data: null,
      );
    }
  }

  _wrapParams(Map<String, dynamic> params) {
    params['t'] = DateTime.now().millisecondsSinceEpoch;
    params['token'] = Auth.instance.token;
    params['nonce'] = Random().nextInt(1000000);
    params['sign'] = _getSign(params);
  }

  String _getSign(Map<String, dynamic> params) {
    var dataArray = new List<String>();
    var keys = params.keys.toList();
    keys.sort();
    for (var key in keys) {
      var val = _getParams(params[key]);
      if (val.isNotEmpty) {
        dataArray.add('$key=$val');
      }
    }
    if (Auth.instance.secret.isNotEmpty) {
      dataArray.add('secret=${Auth.instance.secret}');
    }
    var sign = dataArray.join('&');
    return sign.toMd5().toUpperCase();
  }

  String _getParams(dynamic val) {
    var destVal = '';

    if (val is String) {
      destVal = val.trim();
    } else if (val is int) {
      destVal = val.toString();
    } else if (val is double) {
      destVal = val.toString();
    } else if (val is bool) {
      destVal = val ? 'true' : 'false';
    }
    return destVal;
  }
}
